#include "rgn.h"

RGN::RGN() {}

RGN::~RGN() {}

hi_s32 RGN::Init(td_s32 chn_num, hi_rgn_handle _handle,ot_rgn_type switch_type) {

    hi_s32 ret = HI_SUCCESS;
    memset(&region, 0x00, sizeof(hi_rgn_attr)); 
    chn.mod_id = HI_ID_VPSS; 
    chn.chn_id = chn_num; // 
    // chn.chn_id = 0;//主码流
    chn.dev_id = 0;
    handle = _handle;
    type = switch_type;
    region.type = switch_type;
    
    // 这里创建region， 如果机芯其他进程已经创建好，这里重复创建也没问题
    hi_mpi_rgn_create(handle, &region);
    return ret;
}

hi_s32 RGN::destroy_region()
{
    hi_s32 ret = HI_SUCCESS;
    ret = hi_mpi_rgn_destroy(handle);
    if (ret != HI_SUCCESS)
    {
        printf("hi_mpi_rgn_destroy failed with %#x!\n", ret);
        return ret;
    }
    return ret;
}

hi_s32 RGN::set_attr(bbox_t box, uint32_t color)
{
    hi_s32 ret = HI_SUCCESS;

    switch (type)
    {
        case HI_RGN_COVEREX:
            ret = set_cover_chn_attr(box, color);
            break;
        case HI_RGN_CORNER_RECTEX:
            ret = set_corner_rect_chn_attr(box, color);
            break;
        default:
            break;
    }
    return ret;
}

hi_s32 RGN::set_cover_chn_attr(bbox_t box, uint32_t color)
{
    hi_s32 ret = HI_SUCCESS;
    int x, y, w, h;

    chn_attr.is_show = HI_TRUE;
    chn_attr.type = HI_RGN_COVEREX;
    chn_attr.attr.coverex_chn.layer = 0;
    chn_attr.attr.coverex_chn.coord = HI_COORD_ABS;
    chn_attr.attr.coverex_chn.coverex.type = OT_COVER_QUAD;
    chn_attr.attr.coverex_chn.coverex.color = color;

    chn_attr.attr.coverex_chn.coverex.quad_attr.is_solid = HI_FALSE;
    chn_attr.attr.coverex_chn.coverex.quad_attr.thick = 8;

    if (box.x % 2 != 0)
        x = box.x + 1;
    else
        x = box.x;

    if (box.y % 2 != 0)
        y = box.y + 1;
    else
        y = box.y;

    if (box.w % 2 != 0)
        w = box.w + 1;
    else
        w = box.w;

    if (box.h % 2 != 0)
        h = box.h + 1;
    else
        h = box.h;

    chn_attr.attr.coverex_chn.coverex.quad_attr.point[0].x = x;
    chn_attr.attr.coverex_chn.coverex.quad_attr.point[0].y = y;

    chn_attr.attr.coverex_chn.coverex.quad_attr.point[1].x = x + w;
    chn_attr.attr.coverex_chn.coverex.quad_attr.point[1].y = y;

    chn_attr.attr.coverex_chn.coverex.quad_attr.point[2].x = x + w;
    chn_attr.attr.coverex_chn.coverex.quad_attr.point[2].y = y + h;

    chn_attr.attr.coverex_chn.coverex.quad_attr.point[3].x = x;
    chn_attr.attr.coverex_chn.coverex.quad_attr.point[3].y = y + h;
    return ret;
}

hi_s32 RGN::set_corner_rect_chn_attr(bbox_t box, uint32_t color)
{
    hi_s32 ret = HI_SUCCESS;

    chn_attr.is_show = HI_TRUE;
    chn_attr.type = HI_RGN_CORNER_RECTEX;

    // corner_rect
    if (box.x % 2 != 0)
        chn_attr.attr.corner_rectex_chn.corner_rect.rect.x = box.x + 1;
    else
        chn_attr.attr.corner_rectex_chn.corner_rect.rect.x = box.x;

    if (box.y % 2 != 0)
        chn_attr.attr.corner_rectex_chn.corner_rect.rect.y = box.y + 1;
    else
        chn_attr.attr.corner_rectex_chn.corner_rect.rect.y = box.y;

    int width = roundDownToMultipleOfFour(box.w);
    int height = roundDownToMultipleOfFour(box.h);
    chn_attr.attr.corner_rectex_chn.corner_rect.rect.width = width;
    chn_attr.attr.corner_rectex_chn.corner_rect.rect.height = height;
    chn_attr.attr.corner_rectex_chn.corner_rect.hor_len = width / 4;   // 水平线长
    chn_attr.attr.corner_rectex_chn.corner_rect.ver_len = height / 4;  // 垂直线长

    chn_attr.attr.corner_rectex_chn.corner_rect.thick = 10;  // 宽度

    // corner_rect_attr
    chn_attr.attr.corner_rectex_chn.corner_rect_attr.corner_rect_type = HI_CORNER_RECT_TYPE_CORNER;
    chn_attr.attr.corner_rectex_chn.corner_rect_attr.color = color;

    chn_attr.attr.corner_rectex_chn.layer = 2;

    return ret;
}

hi_s32 RGN::set_lineex_chn_attr(const std::vector<Vector> &vertices, td_u32 color)
{
    hi_s32 ret = HI_SUCCESS;

    chn_attr.is_show = HI_TRUE;
    chn_attr.type = HI_RGN_LINEEX;

    chn_attr.attr.lineex_chn.thick = 4;
    chn_attr.attr.lineex_chn.color = color;
    chn_attr.attr.lineex_chn.points[0].x = roundDownToMultipleOfFour(vertices[0].X);
    chn_attr.attr.lineex_chn.points[0].y = roundDownToMultipleOfFour(vertices[0].Y);
    chn_attr.attr.lineex_chn.points[1].x = roundDownToMultipleOfFour(vertices[1].X);
    chn_attr.attr.lineex_chn.points[1].y = roundDownToMultipleOfFour(vertices[1].Y);

    return ret;
}

hi_s32 RGN::attach_to_chn()
{
    hi_s32 ret = HI_SUCCESS;
    if (!attach_state)
    {
        ret = hi_mpi_rgn_attach_to_chn(handle, &chn, &chn_attr);
        if (ret != TD_SUCCESS)
        {
            printf("id:%d  hi_mpi_rgn_attach_to_chn Error Code:%#x!\n ", handle, ret);
        }
        // TODO 打印chn,chn_attr信息

        attach_state = true;
    }
    return ret;
}

hi_s32 RGN::detach_from_chn()
{
    hi_s32 ret = HI_SUCCESS;
    ret = hi_mpi_rgn_detach_from_chn(handle, &chn);
    if (ret != TD_SUCCESS)
    {
        printf("hi_mpi_rgn_detach_from_chn Error Code:%#x!\n ", ret);
    }
    attach_state = false;
    return ret;
}

hi_s32 RGN::get_chn_display_attr()
{
    hi_s32 ret = HI_SUCCESS;
    ret = hi_mpi_rgn_get_chn_display_attr(handle, &chn, &chn_attr);
    if (ret != TD_SUCCESS)
    {
        printf("hi_mpi_rgn_get_chn_display_attr Error Code:%#x!\n ", ret);
    }
    return ret;
}

hi_s32 RGN::set_chn_display_attr()
{
    hi_s32 ret = HI_SUCCESS;
    ret = hi_mpi_rgn_set_chn_display_attr(handle, &chn, &chn_attr);
    if (ret != TD_SUCCESS)
    {
        printf("hi_mpi_rgn_set_chn_display_attr Error Code:%#x!\n ", ret);
    }
    return ret;
}

int RGN::roundDownToMultipleOfFour(int num)
{
    // 使用整数除法将num除以4，然后乘以4，从而得到最接近的较小的4的倍数
    return (num / 4) * 4;
}

hi_s32 RGN::draw_NonRecognitionPoly(td_s32 chn_num,std::vector<Polygon>& noRecognitionPolys){
    hi_s32 ret = HI_SUCCESS;
    memset(&region, 0x00, sizeof(hi_rgn_attr));
    chn.mod_id = HI_ID_VPSS;
    chn.chn_id = chn_num;
    chn.dev_id = 0;
    region.type = HI_RGN_LINEEX;

    // const float w_scale = 3840.0f;  
    // const float h_scale = 2160.0f;  
    const float w_scale = 1280.0f;  
    const float h_scale = 720.0f;

    for(uint8_t i = 0; i < noRecognitionPolys.size(); i++){
        if(noRecognitionPolys[i].Vertices.size() < 3)
            continue;
        for(uint8_t j = 0;j < noRecognitionPolys[i].Vertices.size(); j++){
            ret = hi_mpi_rgn_create(30 + j + 5 * i, &region);
            td_u32 color;
            switch (i)
            {
            case 0:
                color=0x00FF00; // 绿色
                break;
            case 1:
                color=0x0000FF; // 蓝色
                break;
            case 2:
                color=0xFFFF00; // 黄色
                break;
            case 3:
                color=0xFF0000; // 红色
                break;
            
            default:
                color = 0xFFFFFF; // 白色
                break;
            }
            
            // 相对坐标转4K绝对坐标
            float x_abs = noRecognitionPolys[i].Vertices[j].X * w_scale;
            float y_abs = noRecognitionPolys[i].Vertices[j].Y * h_scale;
            // 下一点坐标（闭合多边形）
            float next_x_abs, next_y_abs;
            if(j == noRecognitionPolys[i].Vertices.size()-1){
                next_x_abs = noRecognitionPolys[i].Vertices[0].X * w_scale;
                next_y_abs = noRecognitionPolys[i].Vertices[0].Y * h_scale;
            }else{
                next_x_abs = noRecognitionPolys[i].Vertices[j+1].X * w_scale;
                next_y_abs = noRecognitionPolys[i].Vertices[j+1].Y * h_scale;
            }

            std::vector<Vector> vertices_abs = {
                Vector(x_abs, y_abs),
                Vector(next_x_abs, next_y_abs)
            };
            set_lineex_chn_attr(vertices_abs,color);

            ret = hi_mpi_rgn_attach_to_chn( 30 + j + 5 * i, &chn, &chn_attr);
            if (ret != TD_SUCCESS) {
                printf("hi_mpi_rgn_attach_to_chn Error Code:%#x!\n ",ret);
            }
        }
    }
    return ret;
}

hi_s32 RGN::clear_NonRecognitionPoly(std::vector<Polygon>& noRecognitionPolys){
    hi_s32 ret = HI_SUCCESS;
    for(uint8_t i=0;i<noRecognitionPolys.size();i++){
        if(noRecognitionPolys[i].Vertices.size() <3 )
            continue;
        for(uint8_t j = 0; j < noRecognitionPolys[i].Vertices.size(); j++){
            ret = hi_mpi_rgn_detach_from_chn( 30 + j + 5 * i, &chn);
            if (ret != TD_SUCCESS) {
                printf("hi_mpi_rgn_detach_from_chn Error Code:%#x!\n ",ret);
            }
            ret = hi_mpi_rgn_destroy( 30 + j + 5 * i);
            if (ret != HI_SUCCESS) {
                printf("hi_mpi_rgn_destroy failed with %#x!\n", ret);
                return ret;
            }
        }
    }
    return ret;
}